<template>
  <el-card class="box-card">
    <slot name="header"></slot>
    <el-table
      ref="tableSection"
      :data="tableData"
      :key="onlykey ? onlykey : ''"
      row-key="id"
      :row-style="rowStyle"
      :cell-style="changeCellStyle"
      @cell-dblclick="cell_dblclick"
      v-loading="pagination ? pagination.loading : noPageLoading"
      :highlight-current-row="highlight"
      style="width: 100%"
      :row-class-name="tableRowClassName"
      @row-click="handleRowClick"
      @header-click="headerRowClick"
      @row-dblclick="handledbRowClick"
      :max-height="height"
      @selection-change="handleSelectionChange"
      :tree-props="treeProps"
    >
      <!-- :max-height="height && height === 'auto' ? null : tableHeight" -->
      <el-table-column
        v-if="checkedStatusShow == 2"
        type="selection"
        width="55"
        align="center"
        fixed="left"
      ></el-table-column>
      <el-table-column
        v-if="checkedStatusShow == 1"
        width="55"
        align="center"
        label="#"
        fixed="left"
      >
        <template slot-scope="scope">
          <el-radio :label="scope.$index" v-model="radio">{{&nbsp;}}</el-radio>
        </template>
      </el-table-column>
      <el-table-column v-if="sequence" width="55" align="center">
        <template slot-scope="scope">
          <div>{{ Number(scope.$index) + 1 }}</div>
        </template>
      </el-table-column>
      <el-table-column
        :class-name="columnState && name === '操作' ? 'buttonStyle' : ''"
        v-for="(
          {
            type,
            fixed = false,
            name,
            value,
            width,
            sortable = true,
            disabled,
            buttonList = [],
            selectList = [],
            fun,
            stateList = [],
            style,
            styleFun,
            header,
            Shower,
            bindData,
            format,
            align,
            slot,
            showLen = 10,
            show_ovflow_tooltip = false,
            valueList = [
              { name: '启用', value: 1 },
              { name: '停用', value: 0 },
            ],
          },
          index
        ) in column"
        :show-overflow-tooltip="show_ovflow_tooltip"
        :fixed="fixed"
        :key="index"
        :label="name"
        :prop="value"
        :width="width"
        :align="align || columnAlign"
        min-width="120"
      >
  
        <template slot="header" slot-scope="scope">
          <span v-html="name"></span>
          <span v-if="header">
            <el-popover
              placement="bottom"
              width="400"
              height="200"
              trigger="click"
            >
              <span slot="reference">
                <i class="el-icon-search" style="color: 'red'" />
              </span>
              <el-date-picker
                value-format="yyyy-MM-dd"
                v-model="dataValue"
                type="daterange"
                range-separator="至"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
                @change="bindData"
              />
              <el-radio-group
                class="radioGroup"
                v-model="dataValue"
                @change="bindData"
              >
                <div style="margin: 10px">
                  <el-radio :label="'11'">昨天</el-radio>
                  <el-radio :label="'12'">今天</el-radio>
                  <el-radio :label="'13'">明天</el-radio>
                </div>
                <div style="margin: 10px">
                  <el-radio :label="'21'">上周</el-radio>
                  <el-radio :label="'22'">本周</el-radio>
                  <el-radio :label="'23'">下周</el-radio>
                </div>
                <div style="margin: 10px">
                  <el-radio :label="'31'">上个月</el-radio>
                  <el-radio :label="'32'">本月</el-radio>
                  <el-radio :label="'33'">下个月</el-radio>
                </div>
                <div style="margin: 10px">
                  <el-radio :label="'41'">去年</el-radio>
                  <el-radio :label="'42'">今年</el-radio>
                  <el-radio :label="'43'">明年</el-radio>
                </div>
              </el-radio-group>
              <div class="el-table-filter__bottom">
                <!-- <button class={this.search ? "" : "is-disabled"}>筛选</button> -->
                <!-- <button on-click={this.clearSearch}>重置</button> -->
              </div>
            </el-popover>
          </span>
        </template>
        <template slot-scope="scope">
          <div v-if="slot">
            <slot :name="value" :scope="scope.row"></slot>
          </div>
          <div v-else-if="type == 'button'">
            <span v-for="(it, i) in buttonList" :key="i">
              <template v-if="it.type === 'no-tooltip'">
                <el-button
                  v-if="
                    !it.showFun || it.showFun(scope.row, scope.$index) === true
                  "
                  v-hasPermi="[it.hasPermiss]"
                  :icon="it.icon ? it.icon : ''"
                  :type="it.color ? it.color : 'primary'"
                  @click="it.fun(scope.row, scope.$index)"
                  size="mini"
                  >{{ it.name }}</el-button
                >
              </template>
              <!-- 下拉框 -->
              <div v-else-if="it.type === 'drop-down'">
                <el-dropdown
                  :trigger="it.dropList.trigger"
                  @command="it.dropList.fun($event, scope)"
                >
                  <el-button
                    :icon="it.icon ? it.icon : ''"
                    :type="it.color ? it.color : 'primary'"
                    size="mini"
                  >
                    {{ it.name }}
                  </el-button>
                  <el-dropdown-menu slot="dropdown">
                    <el-dropdown-item
                      v-for="(drop, index) in it.dropList.data"
                      :command="drop"
                      :key="index"
                      >{{ drop }}</el-dropdown-item
                    >
                  </el-dropdown-menu>
                </el-dropdown>
              </div>
              <template v-else>
                <el-tooltip
                  style="margin: 0 5px 0 5px"
                  v-if="
                    !it.showFun || it.showFun(scope.row, scope.$index) === true
                  "
                  class="item"
                  effect="dark"
                  :content="it.name"
                  placement="top-start"
                >
                  <el-button
                    v-hasPermi="[it.hasPermiss]"
                    :icon="it.icon ? it.icon : ''"
                    :type="it.color ? it.color : 'primary'"
                    @click="it.fun(scope.row, scope.$index)"
                    size="mini"
                    plain
                  ></el-button>
                </el-tooltip>
              </template>
            </span>
          </div>
          <div v-else-if="type == 'switch'">
            <el-tooltip
              :content="
                scope.row[value] === valueList[0].value
                  ? valueList[0].name
                  : valueList[1].name
              "
              placement="top"
            >
              <el-switch
                v-model="scope.row[value]"
                :active-value="valueList[0].value"
                :inactive-value="valueList[1].value"
                active-color="#1890ff"
                inactive-color="#b0adab"
                :disabled="disabled"
                @change="fun(scope.row, scope.$index)"
              ></el-switch>
            </el-tooltip>
          </div>
          <div v-else-if="type == 'image'">
            <el-image
              v-if="scope.row[value]"
              style="width: 50px; height: 50px"
              :src="getRealSrc(scope.row[value])"
              :preview-src-list="[getRealSrc(scope.row[value])]"
              :fit="'cover'"
            >
              <div slot="error" class="image-slot">
                <el-image
                  v-if="defaultUrl"
                  style="width: 50px"
                  :src="defaultUrl"
                  :preview-src-list="[defaultUrl]"
                ></el-image>
              </div>
              <span slot="error"></span>
            </el-image>
            <el-image
              v-else-if="defaultUrl"
              style="width: 50px"
              :src="defaultUrl"
              :preview-src-list="[defaultUrl]"
            ></el-image>
            <!-- <span v-else></span> -->
          </div>
          <div v-else-if="type == 'imageOrText'">
            <el-image
              v-if="
                scope.row[value] &&
                (scope.row[value].indexOf('.jpg') > 0 ||
                  scope.row[value].indexOf('.png') > 0)
              "
              :src="imageUrl + scope.row[value]"
              :preview-src-list="[imageUrl + scope.row[value]]"
            ></el-image>
            <div
              v-if="
                scope.row[value] &&
                scope.row[value].indexOf('.jpg') < 0 &&
                scope.row[value].indexOf('.png') < 0
              "
            >
              {{ scope.row[value] }}
            </div>
            <span slot="error"></span>
            <!-- <span v-else></span> -->
          </div>
          <!-- 下拉框 -->
          <div v-else-if="type == 'select'">
            <el-select
              v-model="scope.row[value]"
              placeholder="请选择"
              @change="fun(scope.row, scope.$index)"
            >
              <el-option
                v-for="item in selectList"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              ></el-option>
            </el-select>
          </div>
          <!-- 单选显示 -->
          <div v-else-if="stateList.length > 0">
            <div v-for="(ik, index) in stateList" :key="index">
              <el-button
                round
                autofocus
                size="mini"
                :type="ik.type"
                v-if="ik.value === scope.row[value] && ik.type"
                plain
                >{{ ik.name }}</el-button
              >
              <span v-else-if="ik.value === scope.row[value]">{{
                ik.name
              }}</span>
            </div>
          </div>
          <!-- 超链接显示 需要手动给tableData里面【需设置超链接】的某行添加el-link属性-->
          <div v-else-if="scope.row.hasOwnProperty('el-link')">
            <el-link :underline="false">
              <span
                @click="linkRowClick(scope.row, index)"
                :style="style ? style : styleFun ? styleFun(scope.row) : ''"
                >{{ scope.row[value] }}</span
              >
            </el-link>
          </div>
          <!-- tooltip显示 -->
          <div v-else-if="type === 'tooltip'">
            <el-tooltip placement="top">
              <template v-slot:content>
                <div style="max-width: 500px">
                  {{ scope.row[value] }}
                </div>
              </template>
              <div>
                {{ scope.row[value] | ellipsis(showLen) }}
              </div>
            </el-tooltip>
          </div>
          <!-- 是否无数据的时候显示无 -->
          <div v-else-if="Shower">
            {{ scope.row[value] ? scope.row[value] : '无' }}
          </div>
          <!-- 添加过滤 -->
          <div v-else-if="format">
            {{ format(scope.row[value]) }}
          </div>

          <div
            v-else
            :style="style ? style : styleFun ? styleFun(scope.row) : ''"
          >
            {{ scope.row[value] }}
          </div>
        </template>
      </el-table-column>
    </el-table>
    <el-table style="display: none" :id="id" :data="excelTableData">
      <el-table-column
        v-for="({ type, name, value }, index) in column.filter(
          (it) => it.type !== 'button'
        )"
        show-overflow-tooltip
        :key="index"
        :label="name"
        :prop="value"
        align="center"
        min-width="120"
      >
        <template slot-scope="scope">
          <div>{{ scope.row[value] }}</div>
        </template>
      </el-table-column>
    </el-table>
    <div
      style="margin-top: 20px"
      v-if="pagination && pagination.limit && !noPage"
    >
      <el-pagination
        background
        :page-size="pagination.limit"
        :page-sizes="pagination.sizes ? pagination.sizes : [10, 20, 50, 100]"
        @size-change="handleSizeChange"
        @current-change="paginationSend"
        :current-page.sync="pagination.page"
        layout="total, sizes, prev, pager, next, jumper"
        :total="pagination.total"
      ></el-pagination>
    </div>
    <div v-else-if="noPage">
      <el-pagination
        background
        :page-size="pagination.limit"
        :page-sizes="pagination.sizes ? pagination.sizes : [10, 20, 50, 100]"
        @size-change="handleSizeChange"
        @current-change="paginationSend"
        :current-page.sync="pagination.page"
        layout="total, prev, next, jumper"
        :total="pagination.total"
      ></el-pagination>
    </div>
    <slot name="footer"></slot>
  </el-card>
</template>
<script>
import { imgDomain } from '@/configs/env';
import { isExternal } from '@/utils/validate';

export default {
  name: 'nxTable',
  props: {
    highlight: {
      type: Boolean,
      default: true,
    },
    noPageLoading: {
      type: Boolean,
      default: false,
    },
    checkboxId: {
      type: Array,
      default: () => {
        return [];
      },
    },
    tableData: {
      type: Array,
      default: () => {
        return [];
      },
    }, // 数据
    onlykey: String, // table唯一标识码
    columnState: Boolean,
    excelTableData: {
      type: Array,
      default: () => {
        return [];
      },
    }, // 需导出的表格数据
    id: String,
    column: Array, // 列名
    sequence: Boolean, // 序号
    selection: {
      required: false, // 是否必填
      type: String, // 类型
    }, // 多选
    height: [String, Number], // 高度
    rowIdChange: {
      required: false,
      type: Function,
    }, // 换行
    checkedStatusShow: {
      default: 0,
      type: Number, // 列表是显示 1是 radio  2 是 checkbox   默认没有选择框
    },
    disabled: false, // 可编辑
    pagination: Object, // 分页对象
    selectionChange: Function, // 选择改变
    rowStyleKey: {
      type: String,
      default: '',
    },
    rowStyleObj: [Object, Function],
    radioKey: {
      type: String,
      default: 'id',
    },
    dbRowClick: {
      type: Function,
      default: () => {},
    },
    headerClick: {
      type: Function,
      default: () => {},
    },
    linkClick: {
      type: Function,
      default: () => {},
    },
    imageUrl: {
      type: String,
      default: imgDomain,
    }, // 地址
    defaultUrl: {
      type: String,
      default: '',
    },
    // loading: Boolean
    autoheight: false,
    minusHeight: {
      type: Number,
      default: 200,
    },
    noPage: {
      type: Boolean,
      default: false,
    },
    columnAlign: {
      type: String,
      default: 'center',
    },
    // 表格二级联动
    treeProps: {
      type: Object,
      default: () => {
        return {
          children: 'children',
        };
      },
    },
  },
  data() {
    return {
      dataValue: '',
      srcList: null, // 预览图片列表
      radio: '', // 序号下标
      radioId: '', // 选中数据Id
      // loading: false,
      tableHeight: 0,
      inputStatus: '', // 表格编辑状态
      timer: null,
      status: true, // 表格编辑状态
    };
  },
  filters: {
    // 超过多少字显示省略号
    ellipsis(value, length) {
      if (!value) return '';
      if (value.length > length) {
        return value.slice(0, length) + '...';
      }
      return value;
    },
  },
  mounted() {},
  methods: {
    changeCellStyle(row, column, rowIndex, columnIndex) {
      if (row.column.label === '产品归属') {
        return 'color: #f00'; // 修改的样式
      } else {
        return '';
      }
    },
    // 行内单元格
    rowStyle({ row, rowIndex }) {
      try {
        if (this.rowStyleObj) {
          if (typeof this.rowStyleObj === 'object') {
            const { key, style, conditions } = this.rowStyleObj;
            if (conditions) {
              if (row[key] === conditions) {
                return style;
              }
            } else {
              if (row[key]) {
                return style;
              }
            }
          } else {
            return this.rowStyleObj(row);
          }
        }
      } catch (e) {
        console.log('行出错');
      }
    },
    // 行的 className 的回调方法
    tableRowClassName({ row, rowIndex }) {
      row.index = rowIndex;
      row.iStatus = false;
      if (this.rowStyleKey) {
        if (row[this.rowStyleKey]) {
          return 'waring-row';
        }
      }
    },
    // 行点击事件
    handleRowClick(val) {
      if (this.checkedStatusShow == 2) {
        this.$refs.tableSection.toggleRowSelection(val);
      } else if (this.checkedStatusShow == 1) {
        this.radio = val.index;
        this.radioId = val[this.radioKey];
      }
      if (this.rowIdChange) {
        this.rowIdChange(val);
      }
    },
    handledbRowClick(row, column, event) {
      this.dbRowClick(row);
    },
    headerRowClick(column, event) {
      this.headerClick(column);
    },
    linkRowClick(row, index) {
      this.linkClick(row, index);
    },
    // 分页 点击页面显示条数时触发
    handleSizeChange(val) {
      this.pagination.page = 1;
      this.pagination.limit = val;
      this.pagination.paginationChange();
    },
    // 分页 点击页数触发
    paginationSend(page) {
      this.pagination.page = page;
      this.pagination.paginationChange();
    },
    // 多选行返回选中行
    handleSelectionChange(val) {
      if (this.selectionChange) {
        this.selectionChange(val);
      }
    },
    //双击复制
    cell_dblclick(row, column, cell, event) {
      var data = cell.innerText;
      var oInput = document.createElement('input');
      oInput.value = data;
      document.body.appendChild(oInput);
      oInput.select();
      document.execCommand('Copy');
      oInput.className = 'oInput';
      oInput.style.display = 'none';
      this.$message.success('复制成功');
    },
    // 监听排序
    sortChange(column, prop, order) {
      /**
       * column.prop 表头字段
       * column.order: ascending 正序 descending 倒序   null 不排
       */
      //
      let orderS = '';
      if (column.order === 'descending') {
        orderS = 'DESC';
      } else if (column.order === 'ascending') {
        orderS = 'ASC';
      }

      this.pagination.sortString = orderS ? column.prop + ' ' + orderS : '';
      this.pagination.paginationChange();
    },
    // 判断图片是否存在
    CheckImgExists(imgurl) {
      const ImgObj = new Image();
      ImgObj.src = '/api' + imgurl;
      // 存在图片
      if (ImgObj.fileSize > 0 || (ImgObj.width > 0 && ImgObj.height > 0)) {
        return true;
      } else {
        return false;
      }
    },
    // 清空选中行
    clearSelect() {
      this.$refs.tableSection.clearSelection();
    },
    // 刷新列表
    refreashTable() {},
    // 排序相关
    sortDevName(str1, str2) {
      console.log(str1);
      console.log(str2);
      let res = 0;
      for (let i = 0; ; i++) {
        if (!str1[i] || !str2[i]) {
          res = str1.length - str2.length;
          break;
        }
        const char1 = str1[i];
        const char1Type = this.getChartType(char1);
        const char2 = str2[i];
        const char2Type = this.getChartType(char2);
        // 类型相同的逐个比较字符
        if (char1Type[0] === char2Type[0]) {
          if (char1 === char2) {
            continue;
          } else {
            if (char1Type[0] === 'zh') {
              res = char1.localeCompare(char2);
            } else if (char1Type[0] === 'en') {
              res = char1.charCodeAt(0) - char2.charCodeAt(0);
            } else {
              res = char1 - char2;
            }
            break;
          }
        } else {
          // 类型不同的，直接用返回的数字相减
          res = char1Type[1] - char2Type[1];
          break;
        }
      }
      return res;
    },
    getChartType(char) {
      // 数字可按照排序的要求进行自定义，我这边产品的要求是
      // 数字（0->9）->大写字母（A->Z）->小写字母（a->z）->中文拼音（a->z）
      if (/^[\u4e00-\u9fa5]$/.test(char)) {
        return ['zh', 300];
      }
      if (/^[a-zA-Z]$/.test(char)) {
        return ['en', 200];
      }
      if (/^[0-9]$/.test(char)) {
        return ['number', 100];
      }
      return ['others', 999];
    },
    getRealSrc(url) {
      if (url) {
        let real_src = url.split(',')[0];
        if (isExternal(real_src)) {
          return real_src;
        }
        return imgDomain + real_src;
      }
      return '';
    },
  },
  watch: {
    // watch监听属性   a代表更新前数据   b代表更新后数据
    $route(to, from) {
      const that = this;
      this.$nextTick(() => {
        that.$refs.tableSection.doLayout();
        that.$refs.tableSection.$el.style.width = '99.99%';
      });
    },
    tableData: function (a, b) {
      this.$nextTick(() => {
        this.$refs.tableSection.doLayout();
      });
      if (this.checkedStatusShow == 2) {
        this.$nextTick(() => {
          if (this.checkboxId.length > 0) {
            a.forEach((row) => {
              if (this.checkboxId.indexOf(row.id) > -1) {
                this.$refs.tableSection.toggleRowSelection(row, true);
              }
            });
          }
        });
      }
      // 判断新数据和旧数据 长度是否相同
      if (a.length > 0 && a.length === b.length) {
        let bool = false;
        a.forEach((it, i) => {
          // 根据上一次选中的数据 去查询新数据里面是否有这一条  如果有就选中 没有就选中第一条
          if (it[this.radioKey] === this.radioId) {
            it.index = i;
            this.handleRowClick(it);
            this.$refs.tableSection.setCurrentRow(it);
            bool = true;
          }
        });
        if (!bool) {
          a[0].index = 0;
          this.handleRowClick(a[0]);
          this.$refs.tableSection.setCurrentRow(a[0]);
        }
      } else if (a.length > 0) {
        // 同理 当新数据长度与旧数据长度不同时
        if (this.radioId) {
          let bool = false;
          a.forEach((it, i) => {
            if (it[this.radioKey] === this.radioId) {
              it.index = i;
              this.handleRowClick(it, i);
              this.$nextTick((it) => {
                this.radio = i;
              });
              this.$refs.tableSection.setCurrentRow(it);
              bool = true;
            }
          });
          if (!bool) {
            a[0].index = 0;
            this.handleRowClick(a[0]);
            this.$refs.tableSection.setCurrentRow(a[0]);
          }
        } else {
          a[0].index = 0;
          this.handleRowClick(a[0]);
          this.$refs.tableSection.setCurrentRow(a[0]);
        }
      }
    },
    radioId: {
      handler(a, b) {},
      deep: true,
    },
    tableHeight: function (a, b) {},
  },
  created() {
    // 区分是否有弹窗
    if (this.height) {
      this.tableHeight = this.height;
    } else {
      if (this.autoheight) this.tableHeight = null;
      else this.tableHeight = window.innerHeight - this.minusHeight - 40;
    }
  },
  activated() {
    this.$nextTick(function () {
      this.$refs.tableSection.doLayout();
    });
  },
  updated() {
    if (this.pagination && this.pagination.loading) {
      clearTimeout(this.timer);
      this.timer = setTimeout(() => {
        this.pagination.loading = false;
      }, 10000);
    } else {
      clearTimeout(this.timer);
    }
    if (this.height) {
      this.tableHeight = this.height;
    } else {
      if (this.autoheight) this.tableHeight = null;
      else {
        this.tableHeight = window.innerHeight - this.minusHeight - 40;
      }
    }
  },
};
</script>
<style lang="scss" scoped>
::v-deep {
  .el-pagination {
    display: flex;
    justify-content: flex-end;
  }
  .el-table .el-table__header-wrapper {
    // height: 44px!important;
  }
  .el-table td.el-table__cell div {
    display: flex;
    justify-content: center;
  }
  .el-table td.el-table__cell.is-left div {
    display: flex;
    justify-content: flex-start;
  }
  .el-table td.el-table__cell.is-right div {
    display: flex;
    justify-content: flex-end;
  }
}
.el-icon-circle-close {
  color: #fff;
}

.el-table__body tr.current-row > td {
  background-color: #c0dbf7;
}
.radioGroup > div {
  display: inline-grid;
  width: 44.6%;
  height: 44px;
}
.el-table__row {
  height: 42px;
}
.buttonStyle .cell {
  padding: 0px !important;
  min-width: 80px !important;
}
.el-table .cell.el-tooltip {
  height: 30px;
  line-height: 30px;
}
.el-table__fixed-body-wrapper .el-table__body {
  padding-bottom: 18px;
}
.el-table__body tr:hover > td {
  color: #000;
}
.el-table__body tr.current-row > td {
  color: #000;
}
</style>
